/* $Id$

Unobtrusive Accessible jQuery 1.2.1 Flash Text Replacement.

Version:
	1.1 (updated 2009/5/15)

Overview:
	jQuery.fn.sifr()
	Based on sifr v2.0.2
	Replaces html text with a Flash object with the same text.
	- Automatic retrieval of some css attributes

Parameters:
	flashSrc: (String) Location of flash font movie
		Default: ''
	// User defined
	flashSrc: '',
	hovercolor: null,
	flashVars: null,
	letterSpacing: 0,
	wmode: 'transparent', // empty/'transparent'/'opaque'
	useFlashDefaults: false,

	// Taken from node
	txt: null,
	url: null,

	// Taken from css if left null, from flash movie if set to "default"
	color: null,
	lineHeight: null,
	fontSize: null,
	textAlign: null,
	letterSpacing: null,
	width: null,
	height: null,
	textDecoration: null

Usage:
	$('.sifrSelector').sifr()

Authors:
	sIFR, gburns

TODO:
	Document
	Look at padding/margins.
	defaults '' or null?
	Probably recode or something :P
*/

(function($) {
$.fn.sifr = function(arguments) {
	var settings = $.extend({
		// User defined
		flashSrc: '',
		hovercolor: null,
		flashVars: null,
		letterSpacing: 0,
		wmode: 'transparent', // empty/'transparent'/'opaque'
		useFlashDefaults: false,
		yOffset: 0,
		heightOffset: 0,

		// Taken from node
		txt: null,
		url: null,

		// Taken from css
		color: null,
		lineHeight: null,
		fontSize: null,
		textAlign: null,
		letterSpacing: null,
		width: null,
		height: null,
		textDecoration: null,
		fontWeight: null,
		fontStyle: null,
		display: null
	}, arguments || {});

	if ( ($.sifr.flashValid == null && !$.sifr.checkFlash()) || ($.sifr.flashValid != null && !$.sifr.flashValid) ) return;

	//var bgcolor = options.bgcolor;
	var bgcolor = 'transparent';
	var flashVars = settings.flashVars || '';
	var wmode = settings.wmode;
	var yOffset = settings.yOffset;
	var display = settings.display;
	flashVars += "&y_offset=" + yOffset;

	var hovercolor = settings.hovercolor;
	if ( hovercolor != null ) hovercolor = $.sifr.getColor(hovercolor);
	if ( hovercolor ) flashVars += "&hovercolor=" + hovercolor;

	/*	Set default values. */
	if ( flashVars ){
		flashVars = '&' + $.sifr.normalize(flashVars);
	} else {
		flashVars = '';	
	}

	if ( wmode == 'transparent' ) bgcolor = 'transparent';
	
	if ( wmode == null ) wmode = '';

	return this.each(function() {
		var $this = $(this);
		//TODO: make this its own method
		var sifrFn = function($that, settings, thatFlashVars) {
			return function() {
				if ( !settings.useFlashDefaults ) {
					var color = settings.color;
					var textAlign = settings.textAlign;
					var textDecoration = settings.textDecoration;
					var letterSpacing = settings.letterSpacing;
					var lineHeight = settings.lineHeight;
					var fontSize = settings.fontSize;
					var fontStyle = settings.fontStyle;
					var fontWeight = settings.fontWeight;

					// TODO: make that a method
					if ( color == null ) color = $.sifr.getColor($that.css('color'));
					if ( textAlign == null ) textAlign = $that.css('textAlign');
					if ( textDecoration == null ) textDecoration = $that.css('textDecoration');
					if ( letterSpacing == null ) letterSpacing = parseInt($that.css('letterSpacing'));
					if ( lineHeight == null ) lineHeight = parseInt($that.css('lineHeight'));
					if ( fontSize == null ) fontSize = parseInt($that.css('fontSize'));
					if ( fontStyle == null ) fontStyle = $that.css('fontStyle');
					if ( fontWeight == null ) fontWeight = $that.css('fontWeight');

					if ( color && color != "default" ) thatFlashVars += "&text_color=" + color;
					if ( textAlign && textAlign != "default" ) thatFlashVars += "&text_align=" + textAlign;
					if ( textDecoration && textDecoration != "default" ) thatFlashVars += "&text_decoration=" + textDecoration;
					if ( letterSpacing && letterSpacing != "default" ) thatFlashVars += "&letter_spacing=" + letterSpacing;
					if ( lineHeight && lineHeight != "default" ) thatFlashVars += "&line_height=" + lineHeight;
					if ( fontSize && fontSize != "default" ) thatFlashVars += "&font_size=" + fontSize;
					if ( fontStyle && fontStyle != "default" ) thatFlashVars += "&font_style=" + fontStyle;
					if ( fontWeight && fontWeight != "default" ) thatFlashVars += "&font_weight=" + fontWeight;
				}

				var url = settings.url;
				if ( url == null ) {
					if ( $this.attr('href') ) {
						url = $this.attr('href');
					} else {
						var $as = $('a', $this);
						if ( $as.length ) {
							url = $as.attr('href');
							display = $as.css('display');
						}
					}
				}
				if ( url ) thatFlashVars += "&url=" + $.sifr.escapeHex(url).replace(/&/g, "%26");
				if ( display ) thatFlashVars += "&display=" + display;

				/* Prevents elements from being replaced multiple times. */
				if ( !$.sifr.flashValid || $that.is('.sIFR-flash') ) return;

				var width = $that.width();
				var height = $that.height();

				if ( !isNaN(parseInt(lineHeight)) && !isNaN(parseInt(fontSize)) && parseInt(fontSize) > parseInt(lineHeight) ) {
					height += parseInt(lineHeight);
				}

				if ( isNaN(width) || isNaN(height) ) return;

				nodeAlternate = $('<span class="sIFR-alternate"></span>')[0];

				oContent = $.sifr.fetchContent($that[0], nodeAlternate, $that.css('textTransform'));

				sVars = "txt=" + $.sifr.normalize($.sifr.escapeHex(oContent.sContent).replace(/\+/g, "%2B").replace(/&/g, "%26").replace(/\"/g, "%22")) + thatFlashVars + "&text_width=" + width + "&text_height=" + height + oContent.sLinkVars;

				/*	Opera only supports the object element, other browsers are given the embed element,
					for backwards compatibility reasons between different browser versions.
					Opera versions below 7.60 use innerHTML, from 7.60 and up we use the DOM */

				if ( !$.browser.msie ) {
					strHTML = ['<embed class="sIFR-flash" type="application/x-shockwave-flash" src="', settings.flashSrc,
								'" quality="best" wmode="', wmode, '" bgcolor="', bgcolor,
								'" flashvars="', sVars.replace(/&/g, '&amp;').replace(/</g, '&lt;'), '" width="', width, '" height="', height,
								'" sifr="true"></embed>'].join("");
				} else {
					strHTML = ['<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" sifr="true" width="', width, '" height="', height,
								'" class="sIFR-flash">',
								'<param name="movie" value="', settings.flashSrc, "?", sVars, '"></param>',
								'<param name="quality" value="best"></param>',
								'<param name="wmode" value="', wmode, '"></param>',
								'<param name="bgcolor" value="', bgcolor, '"></param>',
								'</object>'].join('');
				}

				$that.addClass('sIFR-replaced').empty().append(nodeAlternate).append(strHTML);

				if ( $.browser.msie ) $that[0].outerHTML = $that[0].outerHTML;
			}
		}($this, settings, flashVars); //Do I need to pass options and flashVars?

		if ( $.browser.msie ) {
			$this.css({visibility: 'hidden'});
			$(window).load(function() {
				setTimeout(sifrFn, 0);
			});
		} else {
			sifrFn();
		}
	});
}

$.sifr = {
	flashValid: null,
	flashInstalled: null,
	lastMajorRelease: 10,

	getColor: function(color) {
		var bits = /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(color);
		if ( bits != null ) {
			color = (parseInt(bits[3]) + 256 * parseInt(bits[2]) + 65536 * parseInt(bits[1])).toString(16);
			color = '#' + ('000000' + color).substring(color.length, color.length + 6);
		} else {
			if ( color.length == 4 ) {
				color = ['#', color.substring(1, 2), color.substring(1, 2), color.substring(2, 3), color.substring(2, 3), color.substring(3, 4), color.substring(3, 4)].join("");
			}
		}
		return color;
	},

	checkFlash: function() {
		var flash_plugin;
		var required_version = 7;

		if ( navigator.plugins && navigator.plugins.length ) {
			flash_plugin = navigator.plugins["Shockwave Flash"];
			if (flash_plugin) {
				$.sifr.flashInstalled = true;

				if ( flash_plugin.description ) {
					$.sifr.flashValid = flash_plugin.description.substring(flash_plugin.description.indexOf('.')-3, flash_plugin.description.indexOf('.')).replace(/^\s+/,"");
				}
			} else {
				$.sifr.flashInstalled = false;
			}

			if (navigator.plugins["Shockwave Flash 2.0"]){
				$.sifr.flashInstalled = true;
				$.sifr.flashValid = 2;
			}
		} else if (navigator.mimeTypes && navigator.mimeTypes.length) {

		flash_plugin = navigator.mimeTypes['application/x-shockwave-flash'];

			if ( flash_plugin && flash_plugin.enabledPlugin ) {
				$.sifr.flashInstalled = true;
			} else {
				$.sifr.flashInstalled = false;
			}
		} else {

		for ( var i=$.sifr.lastMajorRelease; i>=2; i-- ) {
				try {
					flash_plugin = new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
					$.sifr.flashInstalled = true;
					$.sifr.flashValid = i;
					break;
				} catch(e) {
				}
			}

			if ( $.sifr.flashInstalled == null ) {
				try {
					flash_plugin = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
					$.sifr.flashInstalled = true;
					$.sifr.flashValid = 2;
				} catch(e) {
				}
			}

			if ( $.sifr.flashInstalled == null ) {
				$.sifr.flashInstalled = false;
			}

			flash_plugin = null;
		}

		return ( $.sifr.flashValid && $.sifr.flashValid >= required_version);
	},

	normalize: function(text) {
		return text.replace(/\s+/g, " ");
	},

	matchNodeName: function(objNode, strMatch){
		return ( strMatch == '*' ) ? true : ( objNode.nodeName.toLowerCase().replace('html:', '') == strMatch.toLowerCase() );
	},

	escapeHex: function(hex){
		if ( $.browser.msie ) { /* The RegExp for IE breaks old Gecko's, the RegExp for non-IE breaks IE 5.01 */
			return hex.replace(new RegExp('%\d{0}', 'g'), '%25');
		}
		return hex.replace(new RegExp('%(?!\d)', 'g'), '%25');
	},

	fetchContent: function(node, nodeNew, textTransform, nLinkCount, sLinkVars) {
		var sContent = '';
		var oSearch = node.firstChild;
		var oRemove, nodeRemoved, oResult, sValue;

		if ( nLinkCount == null ) nLinkCount = 0;
		if ( sLinkVars == null ) sLinkVars = '';

		while(oSearch){
			if(oSearch.nodeType == 3){
				sValue = oSearch.nodeValue.replace("<", "&lt;");
				switch(textTransform){
					case 'capitalize':
						var words = sValue.split(' ');
						for ( var i=0; i < words.length; i++ ) {
							words[i] = words[i].substring(0,1).toUpperCase() + words[i].substring(1, words[i].length);
						}

						sValue = words.join(' ');
						break;
					case 'lowercase':
						sValue = sValue.toLowerCase();
						break;
					case 'uppercase':
						sValue = sValue.toUpperCase();
						break;
					default:
				};

				sContent += sValue;
			} else if(oSearch.nodeType == 1){
				if($.sifr.matchNodeName(oSearch, "a") && !oSearch.getAttribute("href") == false){
					if(oSearch.getAttribute("target")){
						sLinkVars += "&sifr_url_" + nLinkCount + "_target=" + oSearch.getAttribute("target");
					};
					sLinkVars += "&sifr_url_" + nLinkCount + "=" + $.sifr.escapeHex(oSearch.getAttribute("href")).replace(/&/g, "%26");
					sContent += '<a href="asfunction:_root.launchURL,' + nLinkCount + '">';
					nLinkCount++;
				} else if($.sifr.matchNodeName(oSearch, "br")){
					sContent += "<br/>";
				};
				if(oSearch.hasChildNodes()){
					/*	The childNodes are already copied with this node, so nodeNew = null */
					oResult = $.sifr.fetchContent(oSearch, null, textTransform, nLinkCount, sLinkVars);
					sContent += oResult.sContent;
					nLinkCount = oResult.nLinkCount;
					sLinkVars = oResult.sLinkVars;
				};
				if ( $.sifr.matchNodeName(oSearch, 'a') ) {
					sContent += "</a>";
				};
			};

			oRemove = oSearch;
			oSearch = oSearch.nextSibling;
			if(nodeNew != null){
				nodeRemoved = oRemove.parentNode.removeChild(oRemove);
				nodeNew.appendChild(nodeRemoved);	
			};
		};
		
		return {"sContent" : sContent, "nLinkCount" : nLinkCount, "sLinkVars" : sLinkVars};
	}
}
})(jQuery);